package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"battle/api"
	"battle/config"
	"battle/db"
	"battle/user"
)

// initLogFile 初始化日志文件
func initLogFile() (*os.File, error) {
	// 创建日志目录（如果不存在）
	logDir := "log"
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("创建日志目录失败: %w", err)
	}

	// 打开（或创建）日志文件，使用O_TRUNC标志清空文件内容
	logFile := filepath.Join(logDir, "server.log")
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return nil, fmt.Errorf("打开日志文件失败: %w", err)
	}

	return file, nil
}

func main() {
	// 初始化日志文件
	logFile, err := initLogFile()
	if err != nil {
		// 暂时使用标准输出记录错误
		log.Printf("初始化日志文件失败: %v，继续使用标准输出", err)
	} else {
		// 关闭日志文件
		defer logFile.Close()

		// 将日志输出重定向到文件和标准输出（同时输出到两个地方）
		multiWriter := io.MultiWriter(os.Stdout, logFile)
		log.SetOutput(multiWriter)
	}

	// 设置日志格式
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("正在启动虚拟局域网对战平台服务...")

	// 解析命令行参数
	configFile := flag.String("config", "config/config.yaml", "配置文件路径")
	flag.Parse()

	// 加载配置
	cfg, err := config.LoadConfig(*configFile)
	if err != nil {
		log.Printf("加载配置失败: %v，使用默认配置", err)
		cfg = config.DefaultConfig()
	}
	log.Printf("已加载配置: %s", *configFile)

	// 初始化数据库连接
	if err := db.InitMySQL(cfg.MySQL); err != nil {
		log.Fatalf("初始化MySQL连接失败: %v", err)
	}
	log.Println("成功连接到MySQL数据库")

	defer db.CloseMySQLConnection()

	if err := db.InitRedis(cfg.Redis); err != nil {
		log.Fatalf("初始化Redis连接失败: %v", err)
	}
	log.Println("成功连接到Redis数据库")

	// 初始化Redis会话数据
	if err := db.InitRedisData(); err != nil {
		log.Fatalf("初始化Redis数据失败: %v", err)
	}

	defer db.CloseRedisConnection()

	// 创建相关的对象
	userRepo := user.NewSQLRepository(db.MySQLDB)
	userService := user.NewService(userRepo)
	userHandler := user.NewHandler(userService)
	authMiddleware := user.NewAuthMiddleware(userService)

	// 设置路由
	log.Println("正在设置API路由...")
	router := api.SetupRoutes(userHandler, authMiddleware)

	// 创建HTTP服务器
	server := &http.Server{
		Addr:         fmt.Sprintf(":%d", cfg.Server.Port),
		Handler:      router,
		ReadTimeout:  cfg.Server.ReadTimeout,
		WriteTimeout: cfg.Server.WriteTimeout,
		IdleTimeout:  cfg.Server.IdleTimeout,
	}

	// 打印服务器配置
	log.Printf("服务器配置:")
	log.Printf("  端口: %d", cfg.Server.Port)
	log.Printf("  读取超时: %s", cfg.Server.ReadTimeout)
	log.Printf("  写入超时: %s", cfg.Server.WriteTimeout)
	log.Printf("  空闲超时: %s", cfg.Server.IdleTimeout)

	// 在单独的goroutine中启动服务器
	go func() {
		log.Printf("服务器已启动，监听地址 http://localhost:%d", cfg.Server.Port)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("服务器启动失败: %v", err)
		}
	}()

	// 优雅地关闭服务器
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("接收到关闭信号，正在关闭服务器...")

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		log.Fatalf("服务器关闭失败: %v", err)
	}

	log.Println("服务器已成功关闭")
}
